package it.eng.area118.mdogpscollector;

import it.eng.area118.mdocommon.android.util.StringUtils;
import it.eng.area118.mdogpscollector.db.DbManager;
import it.eng.area118.mdogpscollector.db.Item;
import it.eng.area118.mdogpscollector.model.CheckPoint;
import it.eng.area118.mdogpscollector.model.PerstRootBean;
import it.eng.area118.mdogpscollector.service.IndexLookupService;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

import org.garret.perst.Index;
import org.garret.perst.Storage;

public class FillDb {

	/**
	 * @param args
	 * @throws IOException
	 */
	// testModify();
	public static void main(String[] args) throws IOException {
		// prepareAndFill();

		readDb();
		testSaveOrUpdate();
		readDb();
	}

	public static void testSaveOrUpdate() {
		String key = "A1-155-SUD";
		CheckPoint detachedCp = new CheckPoint();
		// System.out.println(detachedCp.getItemKey());
		// System.out.println("Setted input key: " + key);
		detachedCp.setDirection("SUD");
		detachedCp.setType("PAPPA");
		// System.out.println("Setted direction: " + detachedCp);

		/* Storeservice */
		Storage db = DbManager.getDb("db/db.dbs");
		DbManager manager = new DbManager(db);
		PerstRootBean root = (PerstRootBean) db.getRoot();
		Index i = root.getIndex(CheckPoint.class, db, false);
		IndexLookupService service = new IndexLookupService(i, CheckPoint.class, db);
		CheckPoint cp = service.getItem(key);
		// System.out.println("Retrived object from db: " + cp);
		if (cp == null) {
			// insert
		} else {
			// modify

			manager.removeIndex(CheckPoint.class, cp);
			// System.out.println("before modify deatched " + detachedCp);
			// System.out.println("before modify deatched "
			// + detachedCp.getItemKey());
			// System.out.println("before modify attached " + cp);
			// System.out.println("before modify attached " + cp.getItemKey());
			update(detachedCp, cp);
			// System.out.println("after modify deatched " + detachedCp);
			// System.out.println("after modify deatched "
			// + detachedCp.getItemKey());
			// System.out.println("after modify attached " + cp);
			// System.out.println("after modify attached " + cp.getItemKey());

			// manager.removeIndex(CheckPoint.class, cp);
			// System.out.println("after remove detached index " + detachedCp);
			// System.out.println("after remove detached index "
			// + detachedCp.getItemKey());
			// System.out.println("after remove attached index " + cp);
			// System.out
			// .println("after remove attached index " + cp.getItemKey());
			db.storeObject(cp);
			// System.out.println("after storeobj detached index " +
			// detachedCp);
			// System.out.println("after storeobj detached index "
			// + detachedCp.getItemKey());
			// System.out.println("after storeobj attached index " + cp);
			// System.out.println("after storeobj attached index "
			// + cp.getItemKey());
			manager.storeObjectWithIndex(CheckPoint.class, cp);
			// db.commit();
			// System.out.println("after storeObjectWithIndex detached index "
			// + detachedCp);
			// System.out.println("after storeObjectWithIndex attached index "
			// + cp);
			// System.out.println(detachedCp.getItemKey());
			// System.out.println(cp.getItemKey());

		}
		// db.close();
		//
		// // /* RESET */
		// db = DbManager.getDb("db/db.dbs");
		// manager = new DbManager(db);
		// root = (PerstRootBean) db.getRoot();
		// i = root.getIndex(CheckPoint.class, db, false);
		// service = new IndexLookupService(i, CheckPoint.class, db);
		// /* RESET */
		System.out.println("Searching with: " + key);
		List l = service.lookup(key, null);
		System.out.println(l.size());
		System.out.println(l.get(0));
		// db.commit();
		db.close();
	}

	private static String upperCaseFirstChar(String s) {
		String first = new String(s).substring(0, 1).toUpperCase();
		String other = new String(s).substring(1, s.length()).toLowerCase();
		return first + other;
	}

	private static <E> void updateSmipleField(String name, E detachedObj, E fromDb) {
		String sourceValue = "";
		String destValue = "";
		Class<E> sourceClass = (Class<E>) detachedObj.getClass();
		try {

			Field field = sourceClass.getDeclaredField(name);

			try {
				Method met = sourceClass.getMethod("get" + upperCaseFirstChar(name), new Class[] {});
				sourceValue = (String) met.invoke(detachedObj, new Object[] {});
				System.out.println("Source Value for " + name + ": " + sourceValue);
			} catch (Exception e) {

			}

			try {
				Method met = sourceClass.getMethod("get" + upperCaseFirstChar(name), new Class[] {});
				destValue = (String) met.invoke(fromDb, new Object[] {});
				System.out.println("Dest value for " + name + ": " + destValue);
			} catch (Exception e) {

			}

		} catch (SecurityException e) {

		} catch (NoSuchFieldException e) {

		}

		/* update only if is filled the field of the detached object */
		if (!StringUtils.isEmpty(sourceValue)) {
			try {
				Method met = sourceClass.getMethod("set" + upperCaseFirstChar(name), new Class[] { String.class });
				met.invoke(fromDb, new Object[] { sourceValue });
			} catch (SecurityException e1) {

			} catch (NoSuchMethodException e1) {

			} catch (IllegalArgumentException e) {

			} catch (IllegalAccessException e) {

			} catch (InvocationTargetException e) {

			}
		}
	}

	private static void update(CheckPoint detachedObj, CheckPoint fromDb) {
		updateSmipleField("type", detachedObj, fromDb);
		updateSmipleField("direction", detachedObj, fromDb);
	}

	public static void testModify() {
		Storage db = DbManager.getDb("db/db.dbs");
		PerstRootBean root = (PerstRootBean) db.getRoot();
		Index i = root.getIndex(CheckPoint.class, db, false);
		IndexLookupService service = new IndexLookupService(i, CheckPoint.class, db);
		CheckPoint cp = (CheckPoint) service.getAll(null).get(0);
		int ix = 0;
		// while (ix < 100) {
		System.out.println(cp.getDirection());
		System.out.println(cp);
		// cp.setDirection("SUD");
		System.out.println(cp.getDirection());
		db.storeObject(cp);
		db.commit();
		System.out.println(cp);
		ix++;
		System.out.println(cp.getItemKey());
		cp = service.getItem(cp.getItemKey());
		System.out.println(cp);
		// }
		// ;
		db.close();
	}

	public static void readDb() {
		Storage db = DbManager.getDb("db/db.dbs");
		PerstRootBean root = (PerstRootBean) db.getRoot();
		Index i = root.getIndex(CheckPoint.class, db, false);
		IndexLookupService service = new IndexLookupService(i, CheckPoint.class, db);
		List list = service.lookup("A1-155", false, null);
		// List list = service.getAll();
		System.out.println(list.size());
		for (Object object : list) {
			System.out.println(((Item) object));
		}
	}

	public static void prepareAndFill() throws IOException {
		DbManager db = new DbManager("db/db.dbs", DbManager.WRITE_MODE);
		FileInputStream stream = new FileInputStream(new File("puntiDB.txt"));
		InputStreamReader reader = new InputStreamReader(stream);
		BufferedReader buffReader = new BufferedReader(reader);
		List<CheckPoint> points = new ArrayList<CheckPoint>();
		String line = null;
		int cnt = 0;
		String currentDate = "";
		do {
			cnt++;
			line = buffReader.readLine();
			// System.out.println(line);
			if (line != null) {
				CheckPoint p = new CheckPoint();
				String[] split = line.split(" ");
				if (split != null) {
					p.setCoId(split[0]);
					p.setType(split[1]);
					p.setName(split[2]);
					try {
						p.setPoint(String.valueOf(Integer.parseInt(split[4])));
					} catch (Exception e) {
						p.setPoint(String.valueOf(Integer.parseInt(split[3])));
					}
					try {
						p.setDirection(split[5]);
					} catch (Exception e) {
						p.setDirection(null);
					}
					points.add(p);
				}
			}
		} while (line != null);
		buffReader.close();
		fillDb(points, db);
	}

	private static void fillDb(List<CheckPoint> points, DbManager db) {
		for (CheckPoint checkPoint : points) {
			db.storeObjectWithIndex(CheckPoint.class, checkPoint);
		}

	}
}
